package com.haircut.sys.service.dept.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.haircut.sys.constant.Constants;
import com.haircut.sys.dao.dept.SyDeptMapper;
import com.haircut.sys.dao.user.SysUserMapper;
import com.haircut.sys.model.dept.SysDept;
import com.haircut.sys.model.user.SysUser;
import com.haircut.sys.service.dept.IDeptService;
import com.haircut.sys.service.permission.IPermissionService;
import com.haircut.sys.utils.dept.DeptUtils;
import com.haircut.sys.utils.user.SecurityUtils;
import com.haircut.sys.vo.dept.*;
import com.haircut.sys.vo.user.LoginUserVo;
import com.modular.constant.BaseCodeDesc;
import com.modular.constant.NumberConstant;
import com.modular.enums.DataStts;
import com.modular.exception.ModularException;
import com.modular.utils.DBUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class DeptServiceImpl implements IDeptService {

    @Autowired
    @Qualifier("modularSnowflake")
    private Snowflake snowflake;
    @Autowired
    private SyDeptMapper deptMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private IPermissionService permissionService;
    /**
     * 根据角色id集合查询结束名称信息
     * @param deptIdList
     * @return
     */
    @Override
    public Map<String, DeptSimpleVo> findDeptMapByDeptIdList(List<String> deptIdList){
        if(CollUtil.isEmpty(deptIdList)){
            return Collections.emptyMap();
        }
        deptIdList = deptIdList.stream().distinct().toList();
        List<SysDept> roleList = deptMapper.selectBatchIds(deptIdList);
        if(CollUtil.isEmpty(roleList)){
            return Collections.emptyMap();
        }
        return roleList.stream().collect(Collectors.toMap(SysDept::getId, p->{
            DeptSimpleVo simpleVo = new DeptSimpleVo();
            BeanUtils.copyProperties(p,simpleVo);
            return simpleVo;
        }));
    }

    /**
     * 新增部门
     * @param reqVo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveDept(DeptReqVo reqVo)
    {
        if(StrUtil.equals(reqVo.getParentId(), Constants.DEFAULT_PARENT_ID)){
            throw  new ModularException(BaseCodeDesc.DEFATUL_MSG,"不能创建一级部门");
        }
        SysDept pDept = deptMapper.selectById(reqVo.getParentId());
        if(ObjectUtil.isNull(pDept)){
            throw  new ModularException(BaseCodeDesc.DEFATUL_MSG,"上级部门错误");
        }
        Integer deptLevel = DeptUtils.calcDeptLevel(pDept.getDeptLevel());
        if(deptLevel >= NumberConstant.TEN){
            throw  new ModularException(BaseCodeDesc.DEFATUL_MSG,"部门等级不能超过10级");
        }
        String userId = SecurityUtils.getUserId();
        Date currDate = DateUtil.date();
        SysDept dept = new SysDept();
        BeanUtils.copyProperties(reqVo,dept);
        dept.setId(snowflake.nextIdStr());
        dept.setHierarchy(DeptUtils.coverHierarchy(dept.getId(),pDept.getHierarchy()));
        dept.setDeptLevel(pDept.getDeptLevel()+1);
        dept.setGenType(NumberConstant.ZERO);
        dept.setCreateUserId(userId);
        dept.setModifyUserId(userId);
        dept.setCreateDate(currDate);
        dept.setModifyDate(currDate);
        dept.setDataStts(DataStts.ENABLED.getCode());
        dept.setSortNum(Optional.ofNullable(reqVo.getOrderNum()).orElse(NumberConstant.ZERO));
        deptMapper.insert(dept);

    }

    /**
     * 修改部门信息
     * @param reqVo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void modifyDept(DeptReqVo reqVo)
    {
        SysDept dept = deptMapper.selectById(reqVo.getId());
        if(ObjectUtil.isNull(dept)){
            throw  new ModularException(BaseCodeDesc.DEFATUL_MSG,"部门不存在，不能修改");
        }
        String userId = SecurityUtils.getUserId();
        Date currDate = DateUtil.date();
        LambdaUpdateWrapper<SysDept> modify = Wrappers.lambdaUpdate();
        modify.set(SysDept::getModifyDate,currDate).set(SysDept::getModifyUserId,userId);
        modify.set(SysDept::getDeptName,reqVo.getDeptName()).set(SysDept::getSortNum,reqVo.getOrderNum());
        modify.set(SysDept::getParentId,reqVo.getParentId()).set(SysDept::getShareRatio,reqVo.getShareRatio());
        modify.set(SysDept::getGenDay,reqVo.getGenDay());
        modify.eq(SysDept::getId,dept.getId());
        deptMapper.update(modify);

    }

    /**
     * 根据部门id删除部门信息
     * @param deptId
     */
    @Override
    public void deleteById(String deptId)
    {
        SysDept dept = deptMapper.selectById(deptId);
        if(ObjectUtil.isNull(dept)){
            throw  new ModularException(BaseCodeDesc.DEFATUL_MSG,"部门不存在，不能删除");
        }
        LambdaQueryWrapper<SysDept> query = Wrappers.lambdaQuery();
        query.eq(SysDept::getParentId,dept.getId());
        Long count = deptMapper.selectCount(query);
        if(ObjectUtil.isNotNull(count) && count.intValue() > NumberConstant.ZERO){
            throw  new ModularException(BaseCodeDesc.DEFATUL_MSG,"有下级部门，不能删除");
        }
        Long userCount = findUserCount(deptId);
        if(ObjectUtil.isNotNull(userCount) && count.intValue() > NumberConstant.ZERO){
            throw  new ModularException(BaseCodeDesc.DEFATUL_MSG,"部门下有用户，不能删除");
        }
        deptMapper.deleteById(dept.getId());

    }

    private Long findUserCount(String deptId){
        LambdaQueryWrapper<SysUser> query = Wrappers.lambdaQuery();
        query.eq(SysUser::getDeptId,deptId);
        return sysUserMapper.selectCount(query);
    }

    /**
     * 根据部门id查询部门详情
     * @param deptId
     * @return
     */
    @Override
    public DeptDetailVo findDetail(String deptId)
    {
        SysDept dept = deptMapper.selectById(deptId);
        if(ObjectUtil.isNull(dept)){
            throw  new ModularException(BaseCodeDesc.DEFATUL_MSG,"部门不存在，不能删除");
        }
        DeptDetailVo deptDetailVo = new DeptDetailVo();
        BeanUtils.copyProperties(dept,deptDetailVo);
        return deptDetailVo;
    }
    /**
     * 分页查询部门信息
     * @param reqVo
     * @return
     */
    @Override
     public List<DeptPageResVo> findAll(DeptPageReqVo reqVo)
    {
        String parentId = SecurityUtils.getDeptId();
        SysDept dept = deptMapper.selectById(parentId);
        reqVo.setHierarchy(dept.getHierarchy().concat("%"));
        reqVo.setDeptName(DBUtils.escapeQuryLikeParam(reqVo.getDeptName()));
        reqVo.setDataScopeList(permissionService.findPermissionDeptSqlList("t.id"));
        List<DeptPageResVo> list = deptMapper.findAll(reqVo);
        if(ObjectUtil.isNull(list) || CollUtil.isEmpty(list)){
            return Collections.emptyList();
        }
        return list;
    }

    /**
     * 按树形查询部门信息
     * @return
     */
    @Override
    public List<DeptTreeVo> findTree()
    {
        LoginUserVo userVo = SecurityUtils.getLoginUser();
        SysDept  dept = deptMapper.selectById(userVo.getDeptId());
        DeptReqVo reqVo = new DeptReqVo();
        reqVo.setHierarchy(DBUtils.escapeQuryRightLikeParam(dept.getHierarchy()));
        reqVo.setDataScopeList(permissionService.findPermissionDeptSqlList("t.id"));
        List<SysDept> deptList = deptMapper.findPermissionByParentId(reqVo);
        if(CollUtil.isEmpty(deptList)){
            return null;
        }
        DeptTreeVo treeVo = new DeptTreeVo();
        treeVo.setId(dept.getId());
        treeVo.setLabel(dept.getDeptName());
        treeVo.setChildren(DeptUtils.coverTree(deptList,dept.getId()));
        return List.of(treeVo);
    }

    /**
     * 根据id查询部门信息
     * @param deptId
     * @return
     */
    @Override
    public SysDept findById(String deptId){
        return deptMapper.selectById(deptId);
    }

}
